﻿using SRB.Tg.DrawingStandard;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace SRB.Tg.Model
{
   
    static class GlobalFuncs
    {

        /// <summary>
        /// 根据钢筋直径获取单重.
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        public static double GetUnitWeight(eDB d)
        {
            switch (d)
            {
                #region 国标
                case eDB.None:
                    throw (new Exception("钢筋直径错误."));
                // break;
                case eDB.DB6:
                    return 0.222;
                case eDB.DB8:
                    return 0.395;
                case eDB.DB10:
                    return 0.617;
                case eDB.DB12:
                    return 0.888;
                case eDB.DB14:
                    return 1.21;
                case eDB.DB16:
                    return 1.580;
                case eDB.DB20:
                    return 2.47;
                case eDB.DB22:
                    return 2.980;
                case eDB.DB25:
                    //return 3.973;
                    return 3.850;
                case eDB.DB28:
                    return 4.830;
                //return 4.834;
                case eDB.DB32:
                    //return 6.404;
                    return 6.310;
                case eDB.DB36:
                    return 7.99;
                case eDB.DB40:
                    return 9.87;
                default:
                    return 0.0;
                    #endregion

                    #region old 
                    //case eDB.None:
                    //    throw (new Exception("钢筋直径错误."));
                    //// break;
                    //case eDB.DB10:
                    //    return 0.617;
                    //case eDB.DB12:
                    //    return 0.888;
                    //case eDB.DB16:
                    //    return 1.580;
                    //    //return 1.552;
                    //    //return 1.578;
                    //case eDB.DB20:
                    //    return 2.466;
                    //case eDB.DB22:
                    //    return 2.980;
                    //case eDB.DB25:
                    //    //return 3.973;
                    //    return 3.850;
                    //case eDB.DB28:
                    //    return 4.830;
                    //    //return 4.834;
                    //case eDB.DB32:
                    //    //return 6.404;
                    //    return 6.310;
                    //default:
                    //    return 0.0;
                    #endregion
            }
        }


        public static double GetUnitAreaWeight(eDB d,double space)
        {
            //*1.1
            if (space == 10)
            {
                switch (d)
                {
                    #region 国标
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    // break;
                    case eDB.DB5:
                        return 3.08;
                    case eDB.DB6:
                        return 4.44;
                    case eDB.DB7:
                        return 6.04;
                    case eDB.DB8:
                        return 7.9;
                    case eDB.DB9:
                        return 9.98;
                    case eDB.DB10:
                        return 12.33;
                    case eDB.DB11:
                        return 14.92;
                    case eDB.DB12:
                        return 17.75;
                    case eDB.DB14:
                        return 20.98;
                    case eDB.DB16:
                        return 24.68;
                    case eDB.DB18:
                        return 28.86;                 
                    default:
                        return 0.0;
                        #endregion

                }
            }
            else if (space == 15)
            {
                switch (d)
                {
                    #region 国标
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    // break;
                    //case eDB.DB5:
                    //    return 3.08;
                    case eDB.DB6:
                        return 2.96;
                    case eDB.DB7:
                        return 4.03;
                    case eDB.DB8:
                        return 5.26;
                    case eDB.DB9:
                        return 6.66;
                    case eDB.DB10:
                        return 8.22;
                    case eDB.DB11:
                        return 9.95;
                    case eDB.DB12:
                        return 11.84;
                    case eDB.DB14:
                        return 13.99;
                    case eDB.DB16:
                        return 16.46;
                    case eDB.DB18:
                        return 19.25;
                    default:
                        return 0.0;
                        #endregion

                }
            }
            else
            {
                return 0.0;
            }
        }

        public static double GetDevLength(eConcreteClass c, eDB d)
        { 
         if (c == eConcreteClass.C30)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB10:
                        return 300;
                    case eDB.DB12:
                        return 360;
                    case eDB.DB16:
                        return 480;
                    case eDB.DB20:
                        return 600;
                    case eDB.DB25:
                        return 900;
                    case eDB.DB28:
                        return 1130;
                    case eDB.DB32:
                        return 1470;
                    default:
                        return 0;
                }
            }
            else if (c == eConcreteClass.C35)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB10:
                        return 300;
                    case eDB.DB12:
                        return 360;
                    case eDB.DB16:
                        return 480;
                    case eDB.DB20:
                        return 600;
                    case eDB.DB25:
                        return 830;
                    case eDB.DB28:
                        return 1050;
                    case eDB.DB32:
                        return 1360;
                    default:
                        return 0;
                }
            }
            else if (c == eConcreteClass.C45)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB10:
                        return 300;
                    case eDB.DB12:
                        return 360;
                    case eDB.DB16:
                        return 480;
                    case eDB.DB20:
                        return 600;
                    case eDB.DB25:
                        return 750;
                    case eDB.DB28:
                        return 920;
                    case eDB.DB32:
                        return 1200;
                    default:
                        return 0;
                }
            }

            else
            {
                throw (new Exception("混凝土强度错误"));
            }
        }

        public static double GetLapLength(eConcreteClass c, eDB d)
        {
            if (c == eConcreteClass.C30)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB10:
                        return 400;
                    case eDB.DB12:
                        return 480;
                    case eDB.DB16:
                        return 640;
                    case eDB.DB20:
                        return 800;
                    case eDB.DB25:
                        return 1170;
                    case eDB.DB28:
                        return 1470;
                    case eDB.DB32:
                        return 1900;
                    default:
                        return 0;
                }
            }
            else if (c == eConcreteClass.C35)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB10:
                        return 400;
                    case eDB.DB12:
                        return 480;
                    case eDB.DB16:
                        return 640;
                    case eDB.DB20:
                        return 800;
                    case eDB.DB25:
                        return 1080;
                    case eDB.DB28:
                        return 1360;
                    case eDB.DB32:
                        return 1770;
                    default:
                        return 0;
                }
            }
            else if (c == eConcreteClass.C45)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB10:
                        return 400;
                    case eDB.DB12:
                        return 480;
                    case eDB.DB16:
                        return 640;
                    case eDB.DB20:
                        return 800;
                    case eDB.DB25:
                        return 980;
                    case eDB.DB28:
                        return 1200;
                    case eDB.DB32:
                        return 1560;
                    default:
                        return 0;
                }
            }

            else
            {
                throw (new Exception("混凝土强度错误"));
            }
        }

        /// <summary>
        /// 根据钢筋直径输出相应弯钩尺寸，对应h\n\Lx
        /// </summary>
        /// <param name="d"></param>
        /// <param name="angle">90°弯钩、180°弯钩、360°为箍筋stirrup</param>
        /// <returns></returns>
        public static double GetHookLength(eDB d, double angle)
        {
            if (angle == 90)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB32:
                        return 550;
                    case eDB.DB28:
                        return 480;
                    case eDB.DB25:
                        return 400;
                    case eDB.DB20:
                        return 320;
                    case eDB.DB16:
                        return 256;
                    case eDB.DB12:
                        return 192;
                    case eDB.DB10:
                        return 160;
                    default:
                        return 0;
                }
            }
            else if (angle == 180)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB32:
                        return 410;
                    case eDB.DB28:
                        return 370;
                    case eDB.DB25:
                        return 280;
                    case eDB.DB20:
                        return 220;
                    case eDB.DB16:
                        return 180;
                    case eDB.DB12:
                        return 155;
                    case eDB.DB10:
                        return 140;
                    default:
                        return 0;
                }
            }
            else if (angle == 360)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));
                    case eDB.DB32:
                        return 870;
                    case eDB.DB28:
                        return 770;
                    case eDB.DB25:
                        return 690;
                    case eDB.DB20:
                        return 550;
                    case eDB.DB16:
                        return 256;
                    case eDB.DB12:
                        return 192;
                    case eDB.DB10:
                        return 170;
                    default:
                        return 0;
                }
            }
            else if (angle == 135)
            {
                switch (d)
                {
                    case eDB.None:
                        throw (new Exception("钢筋直径错误."));                
                    case eDB.DB16:
                        return 190;
                    case eDB.DB12:
                        return 150;                
                    default:
                        return 0;
                }
            }
            else
            {
                throw (new Exception("弯钩角度输入错误，应为90/135/180/360"));
            }
        }

        public static double GetR(eDB d, double angle)
        {
            if (angle == 90)
            {
                if (d == eDB.DB32 || d == eDB.DB28)
                {
                    return 4 * Convert.ToInt32(d);
                }
                else
                {
                    return 3 * Convert.ToInt32(d);
                }

            }
            else if (angle == 360)
            {
                if (Convert.ToInt32(d) >= 20)
                {
                    return 3 * Convert.ToInt32(d);
                }
                else
                {
                    return 2 * Convert.ToInt32(d);
                }
            }
            else
            {
                throw (new Exception("弯钩角度输入错误，应为90/360"));
            }
        }

        /// <summary>
        /// 获取螺旋筋长度
        /// </summary>
        /// <param name="H">高度</param>
        /// <param name="dia">螺旋筋自身直径</param>
        /// <param name="spacingL">螺旋筋间距</param>
        /// <param name="pileDia">桩径</param>
        /// <returns></returns>
        public static double GetSpiralLength(double H,double dia,double spacingL,double pileDia=1000,double cover=75)
        {
            double innerDia = GetSpiraldia(dia,pileDia, cover);        
            double length = 0;
         
            length = (H / spacingL)*(Math.Sqrt(Math.Pow(Math.PI * (innerDia), 2)+ Math.Pow(spacingL,2)));

            return length;
        }
        public static double GetSpiralLength(double H, double innerDia, double spacingL)
        {
            double length =  (H / spacingL) * (Math.Sqrt(Math.Pow(Math.PI * (innerDia), 2) + Math.Pow(spacingL, 2)));
            return length;
        }
        public static double GetSpiraldia(double dia,double pileDia = 1000, double cover = 75)
        {
            double innerDia = pileDia - 2 * cover - dia;

            return innerDia;
        }
        public static double GetSpiralTopLength( double dia, double num, double pileDia = 1000, double cover = 75)
        {
            double innerDia = GetSpiraldia(dia, pileDia, cover);
            double length  = num * Math.PI * (innerDia);

            return length;
        }
        /// <summary>
        /// 取最近的5或10倍数
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public static double transmit5o10Num(double f)
        {
            f = f * 0.1;
            if ((f - (int)f) <= 0.5 && (f - (int)f > 0))
                return ((int)f + 0.5) * 10;
            if ((f - (int)f) > 0.5)
                return ((int)f + 1.0) * 10;
            if ((f - (int)f) == 0)
                return f * 10;
            return f*10;
        }
   

        /// <summary>
        /// 对一组点通过最小二乘法进行线性回归
        /// </summary>
        /// <param name="parray"></param>
        public static void LinearRegression(Vector2[] parray,out double k,out double b,out double err)
        {
            //点数不能小于2
            if (parray.Length < 2)
            {
                throw new Exception();
            }
            //求出横纵坐标的均值
            double averagex = 0, averagey = 0;
            foreach (Vector2 p in parray)
            {
                averagex += p.X;
                averagey += p.Y;
            }
            averagex /= parray.Length;
            averagey /= parray.Length;
            //经验回归系数的分子与分母
            double numerator = 0;
            double denominator = 0;
            foreach (Vector2 p in parray)
            {
                numerator += (p.X - averagex) * (p.Y - averagey);
                denominator += (p.X - averagex) * (p.X - averagex);
            }
            //回归系数b（Regression Coefficient）
            double RCB = numerator / denominator;
            //回归系数a
            double RCA = averagey - RCB * averagex;
            k = RCB;
            b = RCA;
            //Console.WriteLine("回归系数A： " + RCA.ToString("0.0000"));
            //Console.WriteLine("回归系数B： " + RCB.ToString("0.0000"));
            //Console.WriteLine(string.Format("方程为： y = {0} + {1} * x", RCA.ToString("0.0000"), RCB.ToString("0.0000")));
            //剩余平方和与回归平方和
            double residualSS = 0;  //（Residual Sum of Squares）
            double regressionSS = 0; //（Regression Sum of Squares）
            foreach (Vector2 p in parray)
            {
                residualSS +=
                  (p.Y - RCA - RCB * p.X) *
                  (p.Y - RCA - RCB * p.X);
                regressionSS +=
                  (RCA + RCB * p.X - averagey) *
                  (RCA + RCB * p.X - averagey);
            }
            err = residualSS;
            //Console.WriteLine("剩余平方和： " + residualSS.ToString("0.0000"));
            //Console.WriteLine("回归平方和： " + regressionSS.ToString("0.0000"));
        }


        public static double CalculateReduction(eDB eDB,double ang)
        {
            double Reduction = 0;
            double d = (int)eDB;
            if (ang == 90)
            {
                Reduction = 6 * d * 0.1 - 3 * Math.PI * d * 0.1 * 0.5;
            }
            else if (ang < 90)
            {
                Reduction = 21 * d * 0.1*Math.Tan(GeTools.DegreeToRadian(ang*0.5)) - 0.18326 * d * 0.1 *ang;
            }
            Reduction = double.Parse(Reduction.ToString("0.0"));
            return Reduction;
        }

    }


    /// <summary>
    /// 混泥土强度
    /// </summary>
    public enum eConcreteClass
    {
        None = 0,
        C30 = 0,
        C35 = 35,
        C45 = 45,
        C50 = 50
    };

    /// <summary>
    /// 直径
    /// </summary>
    public enum eDB
    {
        None = 0, DB5 = 5, DB6 = 6, DB7=7, DB8 = 8, DB9 = 9, DB10 = 10, DB11 = 11, DB12 = 12, DB14 = 14, DB16 = 16, DB18 = 18,
        DB20 = 20, DB22 = 22, DB25 = 25, DB28 = 28, DB32 = 32, DB36 = 36, DB40 = 40
    };

}
